package geotag;

import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class Geotagger
{
	private static final String XML = "xml", CSV = "csv";
	private final String BASE_URL = "http://maps.google.com/maps/geo?q={0}&output={1}&key={2}";
	private final String GOOGLE_API_KEY = "ABQIAAAAjyXLt7xcxpmvRyMTawa0XhQgZJysIXBCI10Gq9izJ2r_e-ml4BTB2RTimXNawoCoMiJf_dpijRWoLg";

	/* What we are going to return */
	private String taggedCoordinates = "";
	private AddressTaggedState taggedState = AddressTaggedState.INVALID_LOCATION;

	public Geotagger(String address)
	{
		convertCoordinates(address);
	}

	public AddressTaggedState getTaggedState()
	{
		return taggedState;
	}

	public String getTaggedCoordinates()
	{
		return taggedCoordinates;
	}

	private void convertCoordinates(String originalAddress)
	{
		String geoTaggedResponse = "";

		try
		{
			originalAddress = originalAddress.replace(" ", "%20");

			URL url = new URL(MessageFormat.format(	BASE_URL,
													originalAddress,
													CSV,
													GOOGLE_API_KEY));

			BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
			String line;
			while ((line = reader.readLine()) != null)
			{
				geoTaggedResponse += line;
			}
			reader.close();
		}
		catch (MalformedURLException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}

		/* Now we have to parse the response */
		parseResponse(geoTaggedResponse);
	}

	/*
	 * Parse the response we got back from Google's geotagger service. We will
	 * either get back a JSON response, when they were very specific about the
	 * address, or a string like: "200,4,41.8500330,-87.6500523" if they were
	 * general about the location (which we should flag as a warning on the
	 * final screen), or something like "602,0,0,0" if they entered gobbilygook,
	 * in which case we'll definitely display a warning and not use it as the
	 * starting point.
	 */
	private void parseResponse(String response)
	{
		if (response.startsWith("{"))
		{
			System.out.println("Got a good location");
			
			/*
			 * This is a JSON response, which means they gave us something
			 * specific
			 */
			parseJSONResponse(response);
		}
		else
		{
			System.out.println("Not using the JSON response");
			
			/*
			 * We have a simple CSV string, which means it's either rather
			 * general, or no good. Since we default this.taggedState to
			 * "Invalid Location", we do not need to handle a 602 response,
			 * which is what that means.
			 */
			if (response.startsWith("602") == false)
			{
				/*
				 * The response is useable, but probably too general to be of
				 * any use
				 */
				String[] tokens = response.split(",");

				/*
				 * We need the 2 and 3 elements, which will have the latitude
				 * and longitude, respectively.
				 */
				taggedCoordinates = tokens[2] + "," + tokens[3];
				
				taggedState = AddressTaggedState.GENERALIZED_LOCATION;
			}
		}
	}

	private void parseJSONResponse(String response)
	{
		try
		{
			JSONObject jo = new JSONObject(response);
			JSONArray ja = jo.getJSONArray("Placemark");
			JSONObject jo2 = ja.getJSONObject(0);
			JSONObject coordsObj = jo2.getJSONObject("Point");
			JSONArray coordsArray = coordsObj.getJSONArray("coordinates");

			taggedCoordinates = coordsArray.getString(1) + ","
								+ coordsArray.getString(0);

			taggedState = AddressTaggedState.TAGGED_LOCATION;
		}
		catch (JSONException e)
		{
			e.printStackTrace();
		}
	}
}
